/***************************************************************
*  Copyright (c) 2007 by GroupMe! Team (www.groupme.net)
*  All rights reserved.
*
*  This file is part of the GroupMe! Project. Source code of 
*  this project is closed and redistribution of this code is
*  prohibited. 
*  
*  Contact: http://www.groupme.net
*
*  This copyright notice MUST APPEAR in all copies of the file!
***************************************************************/
package net.groupme.controller;


import java.util.Collection;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.groupme.group.GroupManager;
import net.groupme.gui.constants.VIEW_VOCABULARY;
import net.groupme.gui.rendering.RenderingUtility;
import net.groupme.model.Group;
import net.groupme.model.MODEL_CONSTANTS;
import net.groupme.model.ObjectFactory;
import net.groupme.model.Resource;
import net.groupme.model.ResourceVisualization;
import net.groupme.model.Tag;
import net.groupme.model.User;
import net.groupme.user.UserManager;
import net.groupme.utils.URLUtility;
import net.groupme.utils.sql.TagQueryingUtility;
import net.groupme.utils.sql.UserQueryUtility;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;


/**
 * created on 17 Dec 2007
 * 
 * This class is the Spring Controller that handles requests that are
 * orginated by users when clicking on the Bookmarklet-Button within their browser.
 * 
 * @author Fabian Abel, <a href="mailto:abel@l3s.de">abel@l3s.de</a>
 * @author last edited by: $Author: fabian $
 * 
 * @version $Revision: 1.7 $ $Date: 2008-11-05 13:28:27 $
 */
public class BookmarkletController implements Controller,  ApplicationContextAware {
	
	/** Logger for this class and subclasses */
	protected final Log logger = LogFactory.getLog(getClass());
	
	
	/** the application context */
	ApplicationContext applicationContext = null;
	
	/**
	 * Set the ApplicationContext that this object runs in. 
	 * @param applicationContext the current {@link ApplicationContext} 
	 */
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}
	
	/**
	 * The main method that handles the HTTP requests..
	 * @param request the HTTP request
	 * @param response where we put the model objects..
	 */
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String userRequest = request.getRequestURI();
		//get title, url, .. of the website the user wants to add
		String url = getStringValue(request, VIEW_VOCABULARY.PARAMETER_URL);
		String title = getStringValue(request, VIEW_VOCABULARY.PARAMETER_TITLE);
		
		logger.info("Adding via Bookmarklet - URL: " + url + ", title: " + title);
		
		ModelAndView mav = new ModelAndView();
		if(userRequest.contains(VIEW_VOCABULARY.ACTION_REMOVE_RESOURCE_FROM_QUEUE)){//user simply removes a resource from the queue 
			User user = ((UserManager) applicationContext.getBean(VIEW_VOCABULARY.USER_MANGER, UserManager.class)).getUser();
			UserQueryUtility.getResourceQueueOfUser(user.getId()).removeResource(ObjectFactory.getResource(getStringValue(request, VIEW_VOCABULARY.PARAMETER_ID)));
			mav.setViewName(VIEW_VOCABULARY.VIEW_ADD_OR_REMOVE_FROM_RESOURCEQUEUE_WAS_SUCCESSFUL);
			mav.addObject(VIEW_VOCABULARY.PARAMETER_ID, getStringValue(request, VIEW_VOCABULARY.PARAMETER_ID));
			return mav;
		}else if(userRequest.contains(VIEW_VOCABULARY.ACTION_ADD_TO_GROUP)){//user has selected the group the resource should be added to
			String description = getStringValue(request, VIEW_VOCABULARY.PARAMETER_DESCRIPTION);
			String groupId = getStringValue(request, VIEW_VOCABULARY.PARAMETER_GROUP);
			String keywords = getStringValue(request, VIEW_VOCABULARY.PARAMETER_TAGS);
//			type:
			String type = URLUtility.detectContentType(url);
			Collection<Tag> tags = TagQueryingUtility.getTags(keywords);
			String addedToGroups = "";
			
			String[] groupsToAddTo = request.getParameterValues(VIEW_VOCABULARY.PARAMETER_GROUP);
			GroupManager manager = (GroupManager) applicationContext.getBean(VIEW_VOCABULARY.GROUP_MANGER, GroupManager.class);
			User user = ((UserManager) applicationContext.getBean(VIEW_VOCABULARY.USER_MANGER, UserManager.class)).getUser();
			Group group = null;
			if(groupsToAddTo != null){
				for (int i = 0; i < groupsToAddTo.length; i++) {
					if(VIEW_VOCABULARY.GROUP_QUEUE.equals(groupsToAddTo[i])){
						group = UserQueryUtility.getResourceQueueOfUser(user.getId());
						if(group == null){
							manager.createNewGroup(MODEL_CONSTANTS.QUEUE_GROUP_STANDARD_NAME, MODEL_CONSTANTS.QUEUE_GROUP_STANDARD_DESCRIPTION);
							group = manager.getGroup();
							group.setStandardVisualization(ObjectFactory.createGroupVisualization());
							group.setType(MODEL_CONSTANTS.RESOURCE_TYPE_QUEUE);
						}
					}else{
						group = ObjectFactory.getGroup(groupsToAddTo[i]);
					}
					String groupName = group.getName();
					if(VIEW_VOCABULARY.GROUP_QUEUE.equals(groupsToAddTo[i])){
						addedToGroups += "<a target=\"_blank\" href=\"" + VIEW_VOCABULARY.RESTful_MyGroupMe_QUEUE + "\" title=\"Take a look at your actual Resource Queue...\">Resource Queue</a>";
					}else{
						addedToGroups += "<a target=\"_blank\" href=\"" + VIEW_VOCABULARY.RESTful_GROUP_URI_PATTERN + group.getId() +"\" " +
							" title=\"Arrange resource within group\">" + groupName + "</a>";
					}
					addedToGroups += ((i+1) == groupsToAddTo.length ? "" : ", ");
					manager.setGroup(group);
					manager.setGroupVisualization(group.getStandardVisualization());
					
					//tags: 
					ResourceVisualization resVisu = manager.addResource(title, description, type, url);
					resVisu.setRenderer(RenderingUtility.suggestRenderer(type));
					Resource resource = resVisu.getResource();
					for (Tag tag : tags) {
						resource.addTag(user, tag);
					}
					
				}
			}
			
			mav.addObject(VIEW_VOCABULARY.PARAMETER_URL, url);
			mav.addObject(VIEW_VOCABULARY.PARAMETER_TITLE, title);
			mav.addObject(VIEW_VOCABULARY.PARAMETER_TAGS, keywords);
			mav.addObject(VIEW_VOCABULARY.PARAMETER_DESCRIPTION, description);
			mav.addObject(VIEW_VOCABULARY.PARAMETER_GROUP, addedToGroups);
			
			String resourceId = getStringValue(request, VIEW_VOCABULARY.PARAMETER_ID);
			if(resourceId != null){//User hat eine Ressource aus der Resource Queue in eine Gruppe uebertragen...
				if(groupsToAddTo == null){//user has to select 1 group at least
					mav.setViewName(VIEW_VOCABULARY.VIEW_ADD_TO_GROUP_VIA_RESOURCEQUEUE_FAILED);
					mav.addObject(VIEW_VOCABULARY.PARAMETER_ID, resourceId);
				}else{//-> resource aus Resource Queue loeschen
					UserQueryUtility.getResourceQueueOfUser(user.getId()).removeResource(ObjectFactory.getResource(resourceId));
					mav.setViewName(VIEW_VOCABULARY.VIEW_ADD_OR_REMOVE_FROM_RESOURCEQUEUE_WAS_SUCCESSFUL);
				}
			}else{
				mav.setViewName(VIEW_VOCABULARY.VIEW_ADD_TO_GROUP_VIA_BOOKMARKLET_WAS_SUCCESSFUL);
			}

			logger.info("Add to group with id " + groupId );
		}else{//user comes from another website
			mav.addObject(VIEW_VOCABULARY.PARAMETER_URL, url);
			mav.addObject(VIEW_VOCABULARY.PARAMETER_TITLE, title);
			
			mav.setViewName(VIEW_VOCABULARY.VIEW_ADD_TO_GROUP_VIA_BOOKMARKLET);
		}
		return mav;
	}

    /**
     * Very small helper function to extract a given parameter or attribute from a HttpServletRequest.
     * @param request the {@link HttpServletRequest} object
     * @param parameter the parameter
     * @return the value of the parameter as a String
     */
    private String getStringValue(HttpServletRequest request, String parameter){
    	String value = request.getParameter(parameter);
    	if(value == null && request.getAttribute(parameter) != null){ //normally this is not accessed but we do our best to extract the value.. 
    		value = request.getAttribute(parameter).toString();
    	}
    	return value;
    }
}
